#include "dahengcamera.h"

DahengCamera::DahengCamera() {}

DahengCamera::DahengCamera(QWidget* pWidget,QString ip)
    : m_strIP(ip)
    , m_pWidget(pWidget)
    , m_hDevice(NULL)
    , m_ui32DeviceNum(0)
    , m_strTriggerMode("On")
{
}

DahengCamera::~DahengCamera() {
    OnClose();
}

//掉线回调处理函数
static void GX_STDC OnDeviceOfflineCallbackFun(void* pUserParam)
{
    //收到掉线通知后，由用户主动发送通知主线程停止采集或者关闭设备等操作…
    //QMessageBox::warning(NULL,"警告","相机掉线！", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
    qDebug() << "相机掉线！";
    DahengCamera* pCamera = (DahengCamera*)pUserParam;
    if(pCamera != NULL){
        pCamera->SetSnap(FALSE);
        pCamera->SetOpen(FALSE);
        pCamera->ClearWidget();
    }
    return;
}

//图像回调处理函数
static void GX_STDC OnFrameCallbackFun(GX_FRAME_CALLBACK_PARAM* pFrame)
{
    CGXBitmap* pBitmap = (CGXBitmap*)pFrame->pUserParam;
    if (pFrame->status == GX_FRAME_STATUS_SUCCESS)
    {
        //对图像进行某些操作
        pBitmap->Show(pFrame);
    }
    return;
}

QString DahengCamera::GetIP(){
    return m_strIP;
}

int DahengCamera::OpenDevice()
{
    uint32_t nDSNum;
    stOpenParam.accessMode = GX_ACCESS_EXCLUSIVE;
    stOpenParam.openMode = GX_OPEN_IP;
    QByteArray ba = m_strIP.toLatin1();
    stOpenParam.pszContent = ba.data();

    /*emStatus = GXUpdateAllDeviceList(&m_ui32DeviceNum,1000);
    if(m_ui32DeviceNum <= 0){
        //QMessageBox::warning(NULL,"警告","没有发现相机！", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        qDebug() << "没有发现相机！";
        return emStatus;
    }*/
    // 如果设备已经打开则关闭，保证相机在初始化出错情况能再次打开
    if(m_hDevice != NULL){
        emStatus = GXCloseDevice(m_hDevice);
        m_hDevice = NULL;
    }
    // 打开设备
    // -5 无效参数,一般是指针为NULL或输入的IP等参数格式无效
    emStatus = GXOpenDevice(&stOpenParam,&m_hDevice);
    if(emStatus != GX_STATUS_SUCCESS){
        qDebug() << QString("打开相机失败：%1!").arg(emStatus);
        return emStatus;
    }

    SetOpen(TRUE);

    // 获取流通道数
    emStatus = GXGetDataStreamNumFromDev(m_hDevice,&nDSNum);
    if(nDSNum > 0){
        emStatus = GXGetDataStreamHandleFromDev(m_hDevice,1,&m_hStream);
    }

    // 建议用户在打开网络相机之后，根据当前网络环境设置相机的流通道包长值
    // 以提高网络相机的采集性能，设置方法如下
    {
        bool bImplementPackSize = false;
        uint32_t unPacketSize = 0;

        // 判断设备是否支持流通道数据包功能
        GX_NODE_ACCESS_MODE emAccessMode = GX_NODE_ACCESS_MODE_NI;
        emStatus = GXGetNodeAccessMode(m_hDevice,"GevSCPSPacketSize",&emAccessMode);

        if((emAccessMode != GX_NODE_ACCESS_MODE_NI)
            && (emAccessMode != GX_NODE_ACCESS_MODE_UNDEF)
            && (emAccessMode != GX_NODE_ACCESS_MODE_NA)){
            bImplementPackSize = true;
        }

        if(bImplementPackSize){
            emStatus = GXGetOptimalPacketSize(m_hDevice,&unPacketSize);

            emStatus = GXSetIntValue(m_hDevice,"GevSCPSPacketSize",unPacketSize);
        }
    }

    do{
        m_hWidgetCamera = (HWND)m_pWidget->winId();
        m_pBitmap = new CGXBitmap(m_hDevice,m_hWidgetCamera);
    }while(false);

    return emStatus;
}

int DahengCamera::InitDevice(QString triggerMode){
    GX_STATUS emStatus = GX_STATUS_SUCCESS;
    m_strTriggerMode = triggerMode;

    //设置触发模式为 ON
    emStatus = GXSetEnumValueByString(m_hDevice, "TriggerMode", triggerMode.toLatin1());
    // 设置采集模式连续采集
    emStatus = GXSetEnumValueByString(m_hDevice,"AcquisitionMode","Continuous");
    // 已知当前相机支持哪个8位图像数据格式可以直接设置
    // 例如设备支持数据格式GX_PIXEL_FORMAT_BAYER_GR8,则可按照以下代码实现
    // emStatus = GXSetEnumValue(m_hDevice,"PixelFormat","BayerGR8");

    return emStatus;
}

int DahengCamera::ConfigCaptureVideo()
{
    // 为图像显示准备资源
    emStatus = m_pBitmap->PrepareForShowImg();
    if(emStatus != GX_STATUS_SUCCESS){
        return emStatus;
    }
    // 注册图像采集回调函数
    emStatus = GXRegisterCaptureCallback(m_hDevice,m_pBitmap,OnFrameCallbackFun);
    if(emStatus != GX_STATUS_SUCCESS){
        //QMessageBox::warning(NULL,"警告","注册图像采集回调函数！", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        qDebug() << "注册图像采集回调函数！";
        return emStatus;
    }

    //注册设备掉线回调函数
    emStatus = GXRegisterDeviceOfflineCallback(m_hDevice,this,
                                    OnDeviceOfflineCallbackFun,
                                    &m_hDevcieOfflineCallBack);
    if(emStatus != GX_STATUS_SUCCESS){
        //QMessageBox::warning(NULL,"警告","注册设备掉线回调函数失败！", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        qDebug() << "注册设备掉线回调函数失败！";
        return emStatus;
    }
    //---------------------
    //
    //事件通知会通过 OnDeviceOfflineCallbackFun 接口返给用户
    //
    //---------------------

    // 设置流层Buffer处理模式
    emStatus = GXSetEnumValueByString(m_hStream,"StreamBufferHandlingMode","OldestFirst");
    // 设置流层Buffer处理模式
    //emStatus = GXSetEnumValueByString(m_hStream,"StreamBufferHandlingMode","NewestOnly");
    if(emStatus != GX_STATUS_SUCCESS){
        //QMessageBox::warning(NULL,"警告","设置流层Buffer处理模式失败！", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        qDebug() << "设置流层Buffer处理模式失败！";
        return emStatus;
    }

    return emStatus;
}

int DahengCamera::StartSnap(){
    // 发开始采集命令
    emStatus = GXSetCommandValue(m_hDevice,"AcquisitionStart");
    if(emStatus != GX_STATUS_SUCCESS){
        //QMessageBox::warning(NULL,"警告","相机打开失败！", QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
        qDebug() << "开始相机采集失败!";
        return emStatus;
    }

    this->SetSnap(TRUE);
    return emStatus;
}

/**
 * @brief DahengCamera::TriggerSoftware
 * @return 软触发，是为了采集一张图片
 */

int DahengCamera::TriggerSoftware(){
    //设置触发模式为 ON
    if(m_strTriggerMode == "Off"){
        InitDevice("On");
    }
    StartSnap();
    emStatus = GXSetCommandValue(m_hDevice, "TriggerSoftware");
    return 0;
}
/**
 * @brief DahengCamera::CaptureVideo
 * @return 采集连续的视频，为了调试使用
 */
int DahengCamera::CaptureVideo(){
    if(m_strTriggerMode == "On"){
        InitDevice("Off");
    }
    StartSnap();
    return 0;
}

int DahengCamera::ClearWidget(){
    m_pWidget->setStyleSheet("QWidget { background-color: #FF0000; }");
    return 0;
}

int DahengCamera::StopSnap()
{
    emStatus = GXSetCommandValue(m_hDevice,"AcquisitionStop");
    if(emStatus != GX_STATUS_SUCCESS){
        qDebug()<<"停止相机采集失败!";
    }
    //注销设备掉线事件回调
    GXUnregisterDeviceOfflineCallback(m_hDevice,m_hDevcieOfflineCallBack);

    emStatus = GXUnregisterCaptureCallback(m_hDevice);
    if(emStatus != GX_STATUS_SUCCESS){
        qDebug()<<"UnregisterCaptureCallback failed!";
    }
    return emStatus;
}


int DahengCamera::CloseDevice()
{
    emStatus = GXCloseDevice(m_hDevice);
    if(emStatus != GX_STATUS_SUCCESS){
        qDebug()<<"CloseCamera failed!";
    }
    return emStatus;
}

int DahengCamera::OnClose(){
    GX_STATUS emStatus = GX_STATUS_SUCCESS;

    // 若未停采则先停止采集
    if(this->IsSnap()){
        // 发送停止采集命令
        emStatus = GXSetCommandValue(m_hDevice,"AcquisitionStop");

        // 注销回调
        emStatus = GXUnregisterCaptureCallback(m_hDevice);
        this->SetSnap(FALSE);
    }

    //未关闭设备则关闭设备
    if(this->IsOpen()){
        emStatus = GXCloseDevice(m_hDevice);
        this->SetOpen(FALSE);
        m_hDevice = NULL;
    }

    return emStatus;
}

int DahengCamera::SaveBmp(const char* pFilePath){
    m_pBitmap->SaveBmp(pFilePath);
    return 0;
}

int DahengCamera::SaveJpeg(const char* pFilePath){
    m_pBitmap->SaveJPEG(pFilePath);
    return 0;
}
